#! /bin/bash/env python
# Version .19

## Up frount I want to give some creadit, Some of this code has been recycled from Joe Harringtons Data analysis class.
## Thanks Joe for making some of the coding faster via cut and paste.

from Tkinter import *
import numpy as N
import pyfits as PF
from tkFileDialog import *
from tkMessageBox import *
import RO.DS9
import PyGuide.FindStars
import scipy.fftpack.basic as SPfft
import scipy.ndimage.interpolation as SPinter
import RO.Wdg


#functions for opening
def Openframes():
    #Open if they are the light frames
    
    #This pulls in a list of all of the files to be loaded in
    images = askopenfilenames()
    
    #THis section gets the sizes needed to create the the 3d array
    numimages = len(images)
    tempfile = PF.getdata(images[0], header=False)
    ny, nx = tempfile.shape
    
    #This creates the 3d array to contain the light images
    frames = N.zeros((numimages, ny, nx), dtype=float)
    
    #Lets actualy read in the lights now
    for i in N.arange(numimages):
        frames[i] = PF.getdata(images[i], header=False)
        
    return images, frames


def OpenLight():
    #loads the light rames and then displays tehm to the screen
    global lightframes
    lightimages, lightframes = Openframes()
    
    
    lightbox = Frame(loadframe)
    lightbox.grid(row=2, rowspan=4)
    
    scrolllight = Scrollbar(lightbox, orient=HORIZONTAL)
    fileslist = Listbox(lightbox, xscrollcommand=scrolllight.set)
    scrolllight.config(command=fileslist.xview)
    for item in lightimages:
        fileslist.insert(END, item)
    
    fileslist.pack()
    scrolllight.pack(fill=X)



def OpenDark():
    #opens the darks and displays them to the screen
    global darkframes
    darkimages, darkframes = Openframes()
    
    darkbox = Frame(loadframe)
    darkbox.grid(row=8, rowspan=4)
    
    scrolldark = Scrollbar(darkbox, orient=HORIZONTAL)
    darkslist = Listbox(darkbox, xscrollcommand=scrolldark.set)
    scrolldark.config(command=darkslist.xview)
    for item in darkimages:
        darkslist.insert(END,item)
        
    darkslist.pack()
    scrolldark.pack(fill=X)



def OpenBias():
    #opens the bias and displays them to the screen
    global biasframes
    biasimages, biasframes = Openframes()
    
    biasbox = Frame(loadframe)
    biasbox.grid(row=2, column=2, rowspan=4)
    
    scrollbias = Scrollbar(biasbox, orient=HORIZONTAL)
    biaslist = Listbox(biasbox, xscrollcommand=scrollbias.set)
    scrollbias.config(command=biaslist.xview)
    for item in biasimages:
        biaslist.insert(END, item)
    
    biaslist.pack()
    scrollbias.pack(fill=X)



def OpenFlat():
    #opens the flat frames and displays them to the screen
    global flatframes
    flatimages, flatframes = Openframes()
    
    flatbox = Frame(loadframe)
    flatbox.grid(row=8, column=2, rowspan=4)
    
    scrollflat = Scrollbar(flatbox, orient=HORIZONTAL)
    flatlist = Listbox(flatbox, xscrollcommand=scrollflat.set)
    scrollflat.config(command=flatlist.xview)
    for item in flatimages:
        flatlist.insert(END, item)
    
    flatlist.pack()
    scrollflat.pack(fill=X)



def OpenDarkFlat():
    #opens the flat darks and displays them to the screen
    global darkflatframes
    darkflatimages, darkflatframes = Openframes()
    
     #Display the dark flat list to the screen
    darkflatbox = Frame(loadframe)
    darkflatbox.grid(row=2, column=4, rowspan=4)
    
    scrolldarkflat = Scrollbar(darkflatbox, orient=HORIZONTAL)
    darkflatlist = Listbox(darkflatbox, xscrollcommand=scrolldarkflat.set)
    scrolldarkflat.config(command=darkflatlist.xview)
    for item in darkflatimages:
        darkflatlist.insert(END, item)
    
    darkflatlist.pack()
    scrolldarkflat.pack(fill=X)

def Savefunc():
    #This function is intended to consolodate all of the save functions to one place. It asks what files you would like to save
    #This information is then passed to the save go function
    def savego():
        #This function askes for a save location and name, and based on this and the selection from the outer function it writes
        #the selections.
        location = asksaveasfilename()
        if darkvar != 0:
            PF.writeto(location + '.dark.fits', N.float32(masterdark))
        if biasvar != 0:
            PF.writeto(location + '.bias.fits', N.float32(masterbias))
        if flatvar != 0:
            PF.writeto(location + '.flat.fits', N.float32(masterflat))
        if medvar !=0:
            PF.writeto(location + '.medcombine.fits', N.float32(medfinal))
        if addvar !=0:
            PF.writeto(location + '.add.fits', N.float32(addfile))
        if avgvar !=0:
            PF.writeto(location + '.avg.fits', N.float32(avgfile))
        savewin.destroy()
        
    savewin = Toplevel(width = 500, height = 500)
    
    savemessage = Label(savewin, text="Please select the files you would like to save")
    savemessage.pack()
    
    darkvar = IntVar()
    darkvar = 0
    darkcheck = Checkbutton(savewin, text="Master Dark", variable= darkvar)
    darkcheck.pack()
    
    biasvar = IntVar()
    biasvar = 0
    biascheck = Checkbutton(savewin, text="Master Bias", variable = biasvar)
    darkcheck.pack()
    
    flatvar = IntVar()
    flatvar = 0
    flatcheck = Checkbutton(savewin, text="Master Flat", variable = flatvar)
    flatcheck.pack()
    
    medvar = IntVar()
    medvar = 0 
    medcheck = Checkbutton(savewin, text="Med Light", variable = medvar)
    medcheck.pack()
    
    addvar = IntVar()
    medvar = 0
    addcheck = Checkbutton(savewin, text="Add Light", variable = addvar)
    addcheck.pack()
    
    avgvar = IntVar()
    avgvar = 0
    avgcheck = Checkbutton(savewin, text="Avg Light", variable = avgvar)
    avgcheck.pack()
    
    gosavebutton = Button(savewin, text="Save", command=savego)
    gosavebutton.pack()

##Functions for doing the hard stuff


def biasfunc():
    #This is the bias frunction. It reads in the bias files creates a master Bias by medcombining the bias frames
    #The fuction then asks if you would like to save, and then if you would like to view the frame. It then applies
    #the master bias frame to the light frames.
    #Now medcombine the bias
    global masterbias
    masterbias = medcombine(biasframes)
    
    ds9Win = RO.DS9.DS9Win(doRaise=True)
    ds9Win.showArray(masterbias)
    
    if askyesno(message="Is it ok to apply the bias frame?"):
        global lightframes
        lightframes -= masterbias


def darkfunc():
    #Now medcombine the darks
    global masterdark 
    masterdark = medcombine(darkframes)
    
    ds9Win = RO.DS9.DS9Win(doRaise=True)
    ds9Win.showArray(masterdark)
    
    if askyesno(message="Ok to apply?" ):
        global lightframes
        lightframes -= masterdark


def flatfunc():
    # this function is to produce a flat file to normalize the luminosity of the frame.
    #it is going to check to see if there is darks for the flats, if there is, subtract it
    #after medcombineing them. thse will be subtracted from the flat frames, which will then
    #be medcombine themselves and applied
    global flatframes
    global masterflat
    global lightframes
    if len(darkflatframes) != 0:
        masterdarkflat = medcombine(darkflatframes)
        flatframes -= masterdarkflat
    
    masterflat, flatnorm = medcombinenorm(flatframes)
    
    ds9Win = RO.DS9.DS9Win(doRaise=True)
    ds9Win.showArray(masterflat)
    
    if askyesno(message="Ok to apply?"):
        lightframes /= masterflat
    
def skyfunc():
    def gosky():
        
        normskydata, norm = medcombinenorm(lightframes, y1=y1, y2=y2, x1=x1, x2=x2)
        
        if askyesno(message="Would you like to see the sky frame?"):
            ds9Win = RO.DS9.DS9Win()
            ds9Win.showArray(normskydata)
        
        for k in N.arange(numlight):
            lightframes[k] = lightframes[k] - normskydata * norm[k]
        
        if askyesno(message="Would you like to Display one of the Frames?"):
            ds9Win = RO.DS9.DS9Win()
            ds9Win.showArray(lightframes[0])
        workingwin.destroy()
    
    workingwin = Toplevel(master, height=400, width=400)
    #workingwin.geometry("%dx%d%+d%+d" %(200,500,0,0))
    workingwin.title("Sky Data Entry")
    ds9Win = RO.DS9.DS9Win()
    ds9Win.showArray(lightframes[0])
    
    workingskyframe = Frame(workingwin)
    workingskyframe.grid(row=0, columnspan=2)
    
    infomessage = Label(workingskyframe, text="Please Raise the DS9 window and take a look at the image. \n Select a reagin to compute the normalization from. \n The first click selects the bottem left, and the second the top right")
    infomessage.pack()
    
    skylistbox = Listbox(workingskyframe)
    skylistbox.pack()
    
    e = 0
    while e == 0:
        input1 = ds9Win.xpaget("imexam coordinate image")
        xy1 = input1.split()
        skylistbox.insert(END, "x1:"+xy1[0])
        skylistbox.insert(END, "y1:"+xy1[1])
        input2 = ds9Win.xpaget("imexam coordinate image")
        xy2 = input2.split()
        skylistbox.insert(END, "x2:"+xy2[0])
        skylistbox.insert(END, "y2:"+xy2[1])
    
        if askyesno(message="is this ok?"):
            break
    
    normskydata, norm = medcombinenorm(lightframes, y1=y1, y2=y2, x1=x1, x2=x2)
    
        
    if askyesno(message="Would you like to see the sky frame?"):
        ds9Win = RO.DS9.DS9Win()
        ds9Win.showArray(normskydata)
        
    for k in N.arange(numlight):
        lightframes[k] = lightframes[k] - normskydata * norm[k]
    
    
def alignfunc():
    global lightframes
    global numlight
    #This next function creates a Pyguide CCDInfor class.
    thisccd = PyGuide.CCDInfo(5,7.9,1.4,100000)
    ny, nx = lightframes[0].shape
    numlight = len(lightframes)
    
    def shiftfunc(ny, nx, yoffset, xoffset, index):
        #THis is the funtion that dose the actual shifting. It takes the adjustment parameters and creates larger arrays
        #The orrigional array is then copied entry by entry into the paddedcd array. THe appropriate sides are then trimed 
        #so that the resulting array is the same size as the incomming array. Finally the funtion returns the shifted array
        yrange = ny+abs(int(yoffset))
        xrange = nx+abs(int(xoffset))
        tempframe = N.zeros((yrange, xrange), dtype=float)
        ymove = 0
        xmove = 0
        
        #ok for the moves
        if yoffset < 0:
            ymove = 0
        if yoffset > 0:
            ymove = abs(int(yoffset))
        if xoffset < 0:
            xmove = 0
        if xoffset > 0:
            xmove = abs(int(xoffset))
        
        for l in range(ymove, ny+ymove):
            for m in range(xmove, nx+xmove):
                tempframe[l, m] = lightframes[index, l-ymove, m-xmove]
        
        if yoffset < 0 and xoffset < 0:
            tempframe = tempframe[abs(int(yoffset)):yrange,abs(int(xoffset)):xrange]
            
        
        if yoffset > 0 and xoffset > 0:
            tempframe = tempframe[0:ny,0:nx]
        
        if xoffset < 0 and yoffset > 0:
            tempframe = tempframe[0:ny,abs(int(xoffset)):xrange]
        
        if xoffset > 0 and yoffset < 0:
            tempframe = tempframe[abs(int(yoffset)):yrange,0:nx]
        print tempframe.shape
        return tempframe
        
    tempframe1 = SPfft.fft2(N.log(lightframes[0]))
    for k in N.arange(1, numlight):
        print k
        v = str(k)
        tempframe2 = SPfft.fft2(N.log(lightframes[k]))
        fftcorrection = (tempframe1 * N.conj(tempframe2)) / N.abs(tempframe1 * tempframe2)
        correction = N.real(SPfft.ifft2(fftcorrection))
        
        starslisttemp, starstatstemp = PyGuide.FindStars.findStars(correction, mask=None, satMask=None, ccdInfo=thisccd)
        
        ## Lets put in a test to make sure we have the maximum of the correction
        u = 0.01
        w = 0
        e = 0
        p = 1
        l = 0.3
        while e == 0:
            e = e + p
            while len(starslisttemp) == 0:
                logme.addOutput( "in first loop", tags = ("I"))
                print w
                starslisttemp, starstatstemp = PyGuide.FindStars.findStars(correction, mask=None, satMask=None, ccdInfo=thisccd, thresh=u)
                print starslisttemp
                u = u + l
                w = w +1
                if w > 20:
                    l = 2
                    correction = (N.square(1000*N.abs(correction)))
                if w > 40:
                    correction = N.square(N.square(1000*N.abs(correction)))
                if w > 60:
                    starslisttemp.append(1)
                    p = 0
                    
                
        
        tester = []
        if len(starslisttemp) <1000000:
            if starslisttemp[0] != 1:
                for i in range(len(starslisttemp)):
                    tester.append(starslisttemp[i].counts)
                maxreal = N.argmax(tester, axis=None)
            
                if starslisttemp[maxreal].xyCtr[0] <= (nx/2):
                    xoffset = starslisttemp[maxreal].xyCtr[0]
                if starslisttemp[maxreal].xyCtr[0] > (nx/2):
                    xoffset = starslisttemp[maxreal].xyCtr[0] - nx
                if starslisttemp[maxreal].xyCtr[1] <= (ny/2):
                    yoffset = starslisttemp[maxreal].xyCtr[1]
                if starslisttemp[maxreal].xyCtr[1] > (ny/2):
                    yoffset = starslisttemp[maxreal].xyCtr[1] - ny
            
            logme.addOutput("entering 2nd while loop \n\n", tags =("I"))
            logme.addOutput(starslisttemp, tags=("I"))
            logme.addOutput('\n\n', tags=("N"))
            t = 0
            s = 0.01
            while N.sqrt(N.square(yoffset) + N.square(xoffset)) > 150:
                starslisttemp, starstatstemp = PyGuide.FindStars.findStars(correction, mask=None, satMask=None, ccdInfo=thisccd, thresh=s)
                print starslisttemp
                #scale = len(tester)
                tester =[]
                maxreal = 0 
                if len(starslisttemp) !=0:
                    for i in range(len(starslisttemp)):
                        tester.append(starslisttemp[i].counts)
                        
                    maxreal = N.argmax(tester, axis=None)
                l = 0.3
                
                while len(starslisttemp) == 0:
                    print "in 3rd loop"
                    
                    starslisttemp, starstatstemp = PyGuide.FindStars.findStars(correction, mask=None, satMask=None, ccdInfo=thisccd, thresh=u)
                    print starslisttemp
                    u = u + l
                    w = w +1
                    if w > 20:
                        l = 2
                    if w > 40:
                        l = 3
                
                
                
                print "inside the loop"
                print maxreal
                
                if starslisttemp[maxreal].xyCtr[0] <= (nx/2):
                    xoffset = starslisttemp[maxreal].xyCtr[0]
                if starslisttemp[maxreal].xyCtr[0] > (nx/2):
                    xoffset = starslisttemp[maxreal].xyCtr[0] - nx
                if starslisttemp[maxreal].xyCtr[1] <= (ny/2):
                    yoffset = starslisttemp[maxreal].xyCtr[1]
                if starslisttemp[maxreal].xyCtr[1] > (ny/2):
                    yoffset = starslisttemp[maxreal].xyCtr[1] - ny
                if t == 15:
                    print "The function is hanging"
                t = t + 1
                s = s + 0.7
        
        if len(starslisttemp) == 0:
            xoffset = 0
            yoffset = 0
        print "x:"
        print xoffset
        print "y:"
        print yoffset
        lightframes[k] = shiftfunc(ny, nx , yoffset, xoffset, k)
        
    

def medlight():
    global medfinal
    medfinal = medcombine(lightframes)
    ds9Win = RO.DS9.DS9Win()
    ds9Win.showArray(medfinal)

def addlight():
    global addfile
    numlight = len(lightframes)
    addfile = lightframes[0].copy()
    for k in N.arange(1,numlight):
        addfile = addfile + lightframes[k]
    
    ds9Win=RO.DS9.DS9Win()
    ds9Win.showArray(addfile)

def avglight():
    global avgfile
    avgfile = N.average(lightframes)
    ds9Win=RO.DS9.DS9Win()
    ds9Win.showArray(avgfile)
    
def photometry():
    def tryopen(filename):
        try:
            f = open(filename)
            f.close()
            return True
        except:
            return False
    
    def photogo():
        print photostring
        if tryopen(starlogname) == True:
            editvar = "a"
        if tryopen(starlogname) == False:
            editvar = "w"
        if photostring == 1:
            workframe = addfile
        if photostring == 2:
            workframe = avgfile
        if photostring == 3:
            workframe = medfinal
            print "asigned the workframe"
        starslisttemp, starstatstemp = PyGuide.FindStars.findStars(workframe, mask=None, satMask=None, ccdInfo=thisccd, thresh=01)
        for k in range(len(starslisttemp)):
            logout = open(starlogname+'.txt', editvar)
            logout.write(starslisttemp)
            logout.close()
            editvar = "a"
        photoframe.destroy()
    photoframe = Toplevel(height=400, width=400)
    photoframe.title("Photometry")
    photomessage = Label(photoframe, text="Please Select the data to work on")
    photomessage.pack()
    types = [("Add", 1), ("Average", 2), ("Medcombine",3)]
    global photostring
    photostring = IntVar()
    photostring.set(3)
    for text, mode in types:
        b = Radiobutton(photoframe, text=text,variable=photostring, value=mode)
        b.pack(anchor=W)
    starlognamelabel = Label(photoframe, text="Where would you like your file?")
    starlogname = Button(photoframe, text="save to:", command= asksaveasfile)
    starlogname.pack()
    photosubmitbutton = Button(photoframe, text="Submit", command = photogo)
    photosubmitbutton.pack()

def medcombine(data):
    medcombdat = N.median(data)
    return medcombdat

def medcombinenorm(data, y1=0, y2=-1, x1=0, x2=-1):
    # get sizes, allocate memory
    nz       = data.shape[0]
    norm     = N.ones(nz)
    normdata = data.copy()

    # normalize each frame
    for k in N.arange(nz):
        norm[k]  = N.median( (normdata[k, y1:y2, x1:x2]).flat )
        normdata[k] /= norm[k] # YES!  You can omit trailing dimensions
                           # from [k, :, :], so long as you are taking
                           # all elements in them!

    # median combine them
    medcombdat = medcombine(normdata)

    return medcombdat, norm

def skycormednorm(objdata, normskydata, y1=0, y2=-1, x1=0, x2=-1):
    
    # copy the data
    retval = objdata.copy()
    
    # calculate the normalization
    norm   = N.median((objdata[y1:y2,x1:x2]).flat)
    
    # de-normalize sky and subtract
    retval = retval - norm * normskydata
    
    return retval

def basicreduction():
    global loadframe
    basicframe = Toplevel(master)


    loadframe = Frame(basicframe)
    loadframe.pack(side=LEFT)

    processframe = Frame(basicframe)
    processframe.pack(side=LEFT)

    # Create for Light frames
    lightlabel = Label(loadframe, text="Please Open the Light Frames", borderwidth=2, relief=GROOVE)
    lightlabel.grid(row=0, columnspan=2)

    filesbutton = Button(loadframe, text="Open Files", command=OpenLight, width=13)
    filesbutton.grid(row=1, sticky=W)

    #Get the dark frames
    darklabel = Label(loadframe, text="Please Open the Dark Frames", borderwidth=2, relief=GROOVE)
    darklabel.grid(row=6, columnspan=2)

    darkbutton = Button(loadframe, text="Open Darks", command=OpenDark, width=13)
    darkbutton.grid(row=7, sticky=W)

    #get the Bias Frames
    biaslabel = Label(loadframe, text="Please Open The Bias Frames", borderwidth=2, relief=GROOVE)
    biaslabel.grid(row=0, column=2, columnspan=2, padx=7)

    biasbutton = Button(loadframe, text="Open Bias", command=OpenBias, width=13)
    biasbutton.grid(row=1, column=2, sticky=W, padx=7)

    #Get the Flat Frames
    flatlabel = Label(loadframe, text="Please Open the Flat Frames", borderwidth=2, relief=GROOVE)
    flatlabel.grid(row=6, column=2, columnspan=2, padx=7)

    flatbutton = Button(loadframe, text="Open Flats", command=OpenFlat, width=13)
    flatbutton.grid(row=7, column=2, sticky=W, padx=7)

    #Get darks for the Flat frames
    flatdarklabel = Label(loadframe, text="Please Open the Darks for Flats", borderwidth=2, relief=GROOVE)
    flatdarklabel.grid(row=0, column=4, columnspan=2, padx=7)

    flatdarkbutton = Button(loadframe, text="Open Flat Darks", command=OpenDarkFlat, width=13)
    flatdarkbutton.grid(row=1, column=4,sticky=W, padx=7)

    #apply the corrections
    correctframe = Frame(processframe)
    correctframe.grid(row=1, rowspan=3)

    applylabel = Label(processframe, text="Click to Apply Any of These", borderwidth=2, relief=GROOVE)
    applylabel.grid(row=0, padx=7)

    applyalign = Button(correctframe, text="Align", command=alignfunc, width=13)
    applyalign.pack()

    applydarkbutton = Button(correctframe, text="Darks", command=darkfunc, width=13)
    applydarkbutton.pack()

    applybiasbutton = Button(correctframe, text="Bias", command=biasfunc, width=13)
    applybiasbutton.pack()

    applyskybutton = Button(correctframe, text="Sky Subtraction", width=13, command=skyfunc)
    applyskybutton.pack()

    applyflatsbutton = Button(correctframe, text="Flats", width=13, command=flatfunc)
    applyflatsbutton.pack()

    #things to to do to the image
    functionslabel = Label(processframe, text="What would you like to do with the Data", borderwidth=2, relief=GROOVE)
    functionslabel.grid(row=4, padx=7)

    functionsframe = Frame(processframe)
    functionsframe.grid(row=5, rowspan=3)

    medcombutton = Button(functionsframe, text="Medcomine", command=medlight, width=13)
    medcombutton.pack()

    addcombutton = Button(functionsframe, text="Add", command=addlight, width=13)
    addcombutton.pack()

    avgcombutton = Button(functionsframe, text="Average", command=avglight, width=13)
    avgcombutton.pack()

    photometrybutton = Button(functionsframe, text="Photometry", command=photometry, width=13)
    photometrybutton.pack()
    
    savebutton = Button(functionsframe, text="Save", command=Savefunc, width=13)
    savebutton.pack()

root = Tk()
root.title("Astrogui")
root.geometry("%dx%d%+d%+d" %(600,400,0,0))
master = Frame(root, width=1280, height=1024)
master.pack()

#This next section is creating a log widget so that the progress of this can be outputed to the log instead of the console giving the ability to serach
#and to save
logwin = Toplevel(master)

logme = RO.Wdg.LogWdg(logwin,width=80, height=30)
logme.pack()

bgimage = PhotoImage(file="/Users/nate/Desktop/M1_Crab_Nebula.gif")
mainframe = Label(master, image=bgimage)
mainframe.pack()

Titlelabel = Label(master, text="Astrogui", font="Times 32 bold")
Titlelabel.place(relx=.5, x=-40, y=80)

basicbutton = Button(master, text="Basic Reduction", command=basicreduction)
basicbutton.place(relx=.5, x=-250, y=200, anchor=W)

photometrybutton = Button(master, text="Photometry")
photometrybutton.place(relx=.5, x=-30, y=186)

specbutton = Button(master, text="Spectroscopy")
specbutton.place(relx=.5, x=150, y=185)




root.mainloop()
"""
Version History:
    01-25-08 initial version of the program. Currently has the ability to load light, dark, bias, and flat
             fields. Can apply Darks aswell as porcess medcombine, add, and average.

    01-26-08 Fixed some gui orientation stuff. Also added DS9 support, but added dependencies. Added in Bias
             Support. Titled the project. Added in the sky subtract function. It is supposed to take away the sky
             noise, but it dose not work quite right yet. Fixed a typeo in a button
    
    01-27-08 Edited the bias function. Added the ability to look at the bias frame and approve it before applying it
             also commented the function a bit. Did the same to the Dark function. Added in support for loading dark
             frames for the flat fields. Updated the version number to .13 I added in a routine to align all of the 
             source images. It was a major pain and needs commenting, but hey its done. to only handels x, y movement
             no rotation, but it will get there
             
    01-31-08 I know I did some stuff yesterday, but im not sure exactly what. Today I implemented a check in the alignment
             routine, and if the files are too far out of place, it rejects them. Its not the best, but its a temporary
             work around. Added som ds9 stuff to addlight. Did some bug fixing. Still have not fixed the resize but that
             happens after loading flats. Todo find out how to do image alignment with fft's

    03-18-08 Updated my alignment code to take a log before computing the fft inorder to get better results of alignments.
             Begun to add a simple phtometery routine
             
    03-25-08 After a few days of work withough updating this I am now. I added a log widget so that things can be outputed
             to that instead of the console. This offers the ability to save it, search it, and filter it, though none of 
             these featrure are implemented yet. Also added a base window that allows the selection of basic reductions
             photometry, or sepctroscopy, though the last two still have to be written. Started another file 'incfunc.py'
             that has updated and cleaned up functions. This will eventually get mirged into the code one at a time, to preseve
             a working code base. This incfunc also includes a new save function to consolodate all of the saving to one place
    
    04-03-08 This will hopefull be the last version of astro gui to be represented in TKinter. I will be atempting to move 
             the code to pyqt4 which should provide a cleaner and more useabel code. I hope that the communications interface
             in pyqt will provide a better way to handel function calls. I have updated some of the functions in this version
             as well as adding the save function to one location. The version has been updated to .19, representing the last 
             version for TKinter. Any bug fixing will be a r candidate.
"""